﻿using Coldairarrow.Business.Base_Manage;
using Coldairarrow.Entity.Base_Manage;
using Coldairarrow.Entity.DTO;
using Coldairarrow.Entity.PB;
using Coldairarrow.IBusiness;
using Coldairarrow.Util;
using EFCore.Sharding;
using LinqKit;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace Coldairarrow.Business.PB
{
    public partial class PB_ScheduleBusiness : BaseBusiness<PB_Schedule>, IPB_ScheduleBusiness, ITransientDependency
    {
        readonly IOperator _operator;
        readonly IBase_UserBusiness _UserBusiness;
        public PB_ScheduleBusiness(IDbAccessor db, IOperator @operator, IBase_UserBusiness userBusiness )
            : base(db)
        {
            _operator = @operator;
            _UserBusiness = userBusiness;

        }

        #region 外部接口

        public async Task<PageResult<PB_Schedule>> GetDataListAsync(PageInput<ConditionDTO> input)
        {
            var q = GetIQueryable();
            var where = LinqHelper.True<PB_Schedule>();
            var search = input.Search;

            //筛选
            if (!search.Condition.IsNullOrEmpty() && !search.Keyword.IsNullOrEmpty())
            {
                var newWhere = DynamicExpressionParser.ParseLambda<PB_Schedule, bool>(
                    ParsingConfig.Default, false, $@"{search.Condition}.Contains(@0)", search.Keyword);
                where = where.And(newWhere);
            }

            where=where.And(x => _operator.Property.DeptIds.Contains(x.WorkShopID));
            return await q.Where(where).GetPageResultAsync(input);
        }

        public async Task<PB_Schedule> GetTheDataAsync(string id)
        {
            return await GetEntityAsync(id);
        }

        public async Task AddDataAsync(PB_Schedule data)
        {
            await InsertAsync(data);
        }

        public async Task UpdateDataAsync(PB_Schedule data)
        {
            await UpdateAsync(data);
        }

        public async Task DeleteDataAsync(List<string> ids)
        {
            ///删除主表信息同时删除字表信息
            string itemid = "";
            foreach (var item in ids)
            {
                itemid += "'" + item + "',";
            }
            itemid = itemid.Substring(0, itemid.Length - 1);
            await ExecuteSqlAsync("delete  from  PB_ScheduleDetail  where ParentId in (" + itemid + ")");
            await DeleteAsync(ids);
        }

        public  async Task<PageResult<PB_ScheduleDTO>> GetDataListDTO(PageInput<PB_ScheduleConditionDTO> input)
        {
            var search = input.Search;
            Expression<Func<PB_Schedule,Base_Department, PB_ScheduleDTO>> select = (a,c) => new PB_ScheduleDTO
            {
               
                WorkName = c.Name,
            };
            select = select.BuildExtendSelectExpre();
            var q = from a in GetIQueryable().AsExpandable()
                   
                    join c in Db.GetIQueryable<Base_Department>() on a.WorkShopID equals c.Id into ac
                    from c in ac.DefaultIfEmpty()
                    select @select.Invoke(a,c);
            if (!search.Name.IsNullOrEmpty())
            {
                q = q.Where(x => x.WorkName == search.Name);
            }
            if (!search.StartDate.IsNullOrEmpty() && !search.EndDate.IsNullOrEmpty())
            {
                DateTime StartDate = Convert.ToDateTime(Convert.ToDateTime(search.StartDate).Date.ToString());
                DateTime EndDate = Convert.ToDateTime(Convert.ToDateTime(search.EndDate).Date.ToString()).AddDays(1).AddSeconds(-1);
                q = q.Where(x => StartDate <= x.WorkingDate && x.shiftarrangementDate <= EndDate);
            }
            q = q.OrderByDescending (p=>p.WorkingDate) ;

            ///生产排班增加串数据过滤
            q = q.Where(x=>_operator.Property.DeptIds.Contains(x.WorkShopID));
            return await q.GetPageResultAsync(input);
        }

        /// <summary>
        /// 添加 生产排班及明细   添加排班信息 判断人员排没排过   2022/3/8   17:22
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        /// 
        [DataAddLog(UserLogType.生产任务单, "CreatorId", "生产排班")]
        public async Task AddData(PB_ScheduleListDTO data)
        {
            PB_Schedule pB_Schedule = new PB_Schedule
            {
                Id = data.Id,//编号
                CreateTime = data.CreateTime,//创建时间
                CreatorId = data.CreatorId,//创建人
                CreatorRealName = data.CreatorRealName,
                Deleted = data.Deleted,//伪删除
                WorkingDate = data.WorkingDate,//排班日期
                WorkShopID=data.WorkShopID,//
                shiftarrangementDate=data.shiftarrangementDate,//结束日期
                Shifts = data.Shifts,//班次
                Toexamine=data.Toexamine,
                ToExamineId=data.ToExamineId,
                ToExamineName=data.ToExamineName,
                ToExamineTime=data.ToExamineTime,
            };
            int daynumber = (Convert.ToDateTime(data.shiftarrangementDate) - Convert.ToDateTime(data.WorkingDate)).Days + 1;
            List<PB_ScheduleDetail> listdata = new List<PB_ScheduleDetail>();
            Base_User bdata = await Db.GetIQueryable<Base_User>().Where(x => x.Id == _operator.UserId).FirstOrDefaultAsync();
            List<string> a = new List<string>();
            foreach (var item in data.ScheduleDetail)
            {
                for (int i = 0; i < daynumber; i++)
                { 
                    PB_ScheduleDetail pbdata = new PB_ScheduleDetail();
                    pbdata.Id = IdHelper.GetId();
                    pbdata.CreateTime = DateTime.Now;
                    pbdata.Deleted = false;
                    pbdata.CreatorId = _operator.UserId;
                    pbdata.CreatorRealName = bdata.RealName;
                    pbdata.ParentId = data.Id;
                    pbdata.UserId = item.UserId;
                    pbdata.Type = item.Type;
                    pbdata.Nums = item.Nums;
                    pbdata.WorkDate = Convert.ToDateTime(data.WorkingDate).AddDays(i);
                    listdata.Add(pbdata);
                    //var atAllData =await Db.GetListBySqlAsync<PB_ScheduleDetail>("SELECT *  FROM PB_ScheduleDetail   WHERE  UserID='"+ pbdata.UserId +"'  and    WorkDate  between   '"+Convert.ToDateTime(data.WorkingDate)+1+"'     and   '"+data.shiftarrangementDate+"'");
                    string sqlmain = @"SELECT *  FROM PB_ScheduleDetail   WHERE  UserID='" + pbdata.UserId + "'  and    WorkDate  between   '" + Convert.ToDateTime(data.WorkingDate).ToString("yyyy-MM-dd") + "'     and   '" + Convert.ToDateTime(data.shiftarrangementDate).ToString("yyyy-MM-dd") + "'";
                    var atAllData = await Db.GetListBySqlAsync<PB_ScheduleDetail>(sqlmain);
                    if (atAllData.Count > 0)
                    {
                        var q = Db.GetIQueryable<Base_User>().Where(x => x.Id == item.UserId).FirstOrDefault();
                        a.Add(q.RealName);
                    }
                }
            }
            if (a.Count>0) {
               a = a.Distinct<string>().ToList();
                var result = String.Join(",", a.ToArray());
                throw new BusException("该时间段下以下用户已有排班:" + result);
            }
             await Db.InsertAsync(listdata);
            await Db.InsertAsync(pB_Schedule);
        }

        /// <summary>
        /// 修改生产排班 及明细0
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        [DataEditLog(UserLogType.生产任务单, "CreatorId", "生产排班")]
        [Transactional]
        public async Task UpdateData(PB_ScheduleListDTO data)
        {
            string sqlstr = "delete from PB_ScheduleDetail where Id in ( ";
            foreach (var item in data.ScheduleDetail)
            {
                sqlstr += "'" + item.Id + "',";
            }
            sqlstr = sqlstr.Substring(0, sqlstr.Length - 1) + ")";
            await ExecuteSqlAsync(sqlstr);
            var EditPB_ScheduleDetail = data.ScheduleDetail.Select(m => new PB_ScheduleDetail
            {
                Id = IdHelper.GetId(),// id
                CreateTime=data.CreateTime,//创建时间
                CreatorId=data.CreatorId,//创建人
                Deleted=false,//伪删除
                ParentId=data.Id,//主表id
               
                UserId=m.UserId,//用户编号
                Type=m.Type,//班别 0白班  1夜班
                Nums=m.Nums,//加工数量
            }).ToList();
            await Db.InsertAsync(EditPB_ScheduleDetail);
        }

        public IQueryable<T> GetQueryable<T>() where T : class, new()
        {
            return Db.GetIQueryable<T>();
        }

        //通过生产排班 主表 parentid 查找 明细
        public async Task<PB_ScheduleList> GetDataListInfo(string ParentId)
        {
            PB_ScheduleList pblist = new PB_ScheduleList();
            Expression<Func<PB_Schedule, Base_Department, PB_ScheduleDTO>> selects = (a, b) => new PB_ScheduleDTO
            {
                WorkName = b.Name,//部门名称
              
            };
            selects = selects.BuildExtendSelectExpre();
            var qdata = from a in Db.GetIQueryable<PB_Schedule>().AsExpandable()
                        join b in Db.GetIQueryable<Base_Department>() on a.WorkShopID equals b.Id into ab
                        from b in ab.DefaultIfEmpty()
                     
                        select @selects.Invoke(a,b);
            pblist.maiData = await qdata.Where(x => x.Id == ParentId).FirstOrDefaultAsync();
            Expression<Func<PB_ScheduleDetail, PB_Schedule, PB_ProductionOrder, PB_Material, Base_User, PB_ScheduleDetailListDTO>> selectss = (a, b, c, d, e) => new PB_ScheduleDetailListDTO
            {
                TaskIdName = c.POName,
                MaterialName = d.Name,
                UserIdName = e.RealName,
                Deptid=b.WorkShopID,
            };
            Expression<Func<PB_ScheduleDetail, PB_Schedule,  Base_User, PB_ScheduleDetailListDTO>> select = (a, b,  e) => new PB_ScheduleDetailListDTO
            {
             
                UserIdName = e.RealName,
            };

            select = select.BuildExtendSelectExpre();
            var q = from a in Db.GetIQueryable<PB_ScheduleDetail>().AsExpandable()
                    join b in Db.GetIQueryable<PB_Schedule>() on a.ParentId equals b.Id into ab
                    from b in ab.DefaultIfEmpty()
                
                    join e in Db.GetIQueryable<Base_User>() on a.UserId equals e.Id into ae
                    from e in ae.DefaultIfEmpty()

                    select @select.Invoke(a, b, e);
            q = q.Where(x => x.ParentId == ParentId);
            q=q.Where(x => _operator.Property.DeptIds.Contains(x.Deptid));
            pblist.subData = await q.ToListAsync();
            return pblist;
        }

        /// <summary>
        /// 排班审核
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public  async Task UpdateDataStateAsync(string Id)
        {
            await ExecuteSqlAsync("update PB_Schedule set Toexamine=1 where Id='" + Id + "'");
        }

        public async Task<PageResult<PB_ScheduleDTO>> GetDataListToexamineAsync(PageInput<PB_ScheduleConditionDTO> input)
        {
            var search = input.Search;
            Expression<Func<PB_Schedule, Base_Department, PB_ScheduleDTO>> select = (a, c) => new PB_ScheduleDTO
            {

                WorkName = c.Name,
            };
            select = select.BuildExtendSelectExpre();
            var q = from a in GetIQueryable().AsExpandable()

                    join c in Db.GetIQueryable<Base_Department>() on a.WorkShopID equals c.Id into ac
                    from c in ac.DefaultIfEmpty()
                    select @select.Invoke(a, c);
            if (!search.Name.IsNullOrEmpty())
            {
                q = q.Where(x => x.WorkName == search.Name);
            }
            q = q.Where(x => x.Toexamine == 1);
            q = q.OrderByDescending(p => p.WorkingDate);
 

            return await q.GetPageResultAsync(input);
        }

        public async Task ToExamineDataAsync(string id, int stateType)
        {
            await ExecuteSqlAsync("update PB_Schedule set Toexamine='" + stateType + "',ToExamineId='" + _operator.UserId + "',ToExamineName='" + _operator?.Property?.RealName + "',ToExamineTime='" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "' where Id='" + id + "'");
        }

        #endregion

        #region 私有成员

        #endregion
    }
}